#include <stdio.h>
#include <stdlib.h>

struct example {
    int a;
    char *s;
};

void creat(struct example **dp)
{
     *dp = (struct example *) malloc (sizeof(struct example));
     if (dp == NULL) {
          printf("malloc fail.\n");
     }
     (*dp)->a = 99;
     printf("%d\n", (*dp)->a);	// 99
     printf("%d\n", (**dp).a);	// 99
}

int main()
{
    struct example obj = {10, "hello"};
    struct example *p = &obj;
    struct example *dp = NULL;

     printf("%d %d\n", p->a, (*p).a);	// 10 10
     printf("%d\n", (p)->a);		// 10
     // printf("%d\n", (*p)->a); 		// compile error
     printf("%c\n", *p->s);		// 'h'
     printf("%c\n", *(p->s));		// 'h'
     printf("%c\n", *((*p).s));         // 'h'
     printf("%s\n", p->s);			// "hello"

     creat(&dp);
     printf("%d\n", dp->a);	// 99
     printf("%d\n", (*dp).a);	// 99

     return 0;
}

#if 0
表达式(*p)->a的含义是：
   先对指针 p 进行解引用（*p），再通过解引用后的指针访问其指向结构体的成员 a

语法解析
    p：指向结构体的指针
    *p：解引用p，得到结构体实例
    一级指针：p->a：等价于(*p).a，访问结构体成员a的值 ‌
    二级指针：(*p)->a：等价于(**p).a，访问结构体成员a的值 ‌

总结：
    (*p)->a 是二级指针访问结构体成员。


表达式 *p->a 的含义是：
    ->指针操作符的优先级非常高，于是*p->a就是*(p->a),
    取得指针p指向的结构体的成员a（也是指针）指向的第一个元素。

总结：
    *p->a = *(p->a), 一级指针访问结构体成员，见上例。

#endif